using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;

namespace Common
{
    public class TResourceManager
    {
        private Common.Resource resource;

        private Size OriginalSize = new Size(0, 0);
        private Dictionary<string, Dictionary<Size, Bitmap>> bitmapCache;

        public TResourceManager()
        {
            this.resource = new Common.Resource();
            this.resource.Levels = 4;

            this.bitmapCache = new Dictionary<string, Dictionary<Size, Bitmap>>();
        }

        public Bitmap GetBitmap(string filename)
        {
            Bitmap result = this.CheckCache(filename, this.OriginalSize);
            if (result != null) {
                return result;
            }

            result = this.resource.GetBitmap(filename, "bitmaps");
            result.MakeTransparent();
            this.AddToCache(result, filename, true);

            return result;
        }

        public Bitmap GetBitmap(string filename, Size size)
        {
            Bitmap result = this.CheckCache(filename, size);
            if (result != null) {
                return result;
            }

            result = this.resource.GetBitmap(filename, "bitmaps");
            result.MakeTransparent();
            this.AddToCache(result, filename, true);
            Bitmap scaledResult = TResourceManager.Scale(result, size);
            this.AddToCache(scaledResult, filename, false);

            return scaledResult;
        }

        private Bitmap CheckCache(string filename, Size size)
        {
            if (this.bitmapCache.ContainsKey(filename)) {
                if (this.bitmapCache[filename].ContainsKey(size)) {
                    return this.bitmapCache[filename][size];
                }
            }

            return null;
        }

        private void AddToCache(Bitmap bitmap, string filename, bool original)
        {
            if (!this.bitmapCache.ContainsKey(filename)) {
                this.bitmapCache[filename] = new Dictionary<Size, Bitmap>();
            }
            if (original) {
                Trace.Verbose("Adding original: " + filename + " to cache. Size: " + bitmap.Size.ToString(), this.GetType().ToString());
                this.bitmapCache[filename][this.OriginalSize] = bitmap;
            }

            Trace.Verbose("Adding: " + filename + " to cache. Size: " + bitmap.Size.ToString(), this.GetType().ToString());
            this.bitmapCache[filename][bitmap.Size] = bitmap;
        }

        private static Bitmap Scale(Bitmap Bitmap, Size size)
        {
            Bitmap scaledBitmap = new Bitmap(size.Width, size.Height);
            
            // Scale the bitmap in high quality mode.
            using (Graphics g = Graphics.FromImage(scaledBitmap)) {
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                g.DrawImage(Bitmap, new Rectangle(new Point(0, 0), size), new Rectangle(0, 0, Bitmap.Width, Bitmap.Height), GraphicsUnit.Pixel);
            }

            // Copy original Bitmap's EXIF tags to new bitmap.
            foreach (PropertyItem propertyItem in Bitmap.PropertyItems) {
                scaledBitmap.SetPropertyItem(propertyItem);
            }

            return scaledBitmap;
        }

    }
}
